package joey.project1.model

import javax.sound.sampled.AudioFormat
import javax.sound.sampled.AudioInputStream
import javax.sound.sampled.AudioSystem
import javax.sound.sampled.DataLine
import javax.sound.sampled.SourceDataLine

class WavPlay {
	private File file
	private boolean play_stop = false

	public void play(){
		play_stop = false
		Thread.start { _play() }
	}

	public void play_replay(){
		play_stop = false
		Thread.start {
			while(true){
				if(play_stop)
					break
				_play()
			}
		}
	}

	public void play_loop(){
		play_stop = false
		Thread.start { _play(true) }
	}

	private void _play(boolean loop = false){
		AudioInputStream m_audioInputStream = null
		SourceDataLine m_line = null
		AudioFormat audioFormat = null
		try {
			m_audioInputStream = AudioSystem.getAudioInputStream(file)
			audioFormat = m_audioInputStream.getFormat()

			if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
				AudioFormat newFormat = new AudioFormat(
						AudioFormat.Encoding.PCM_SIGNED, audioFormat
						.getSampleRate(), 16, audioFormat.getChannels(),
						audioFormat.getChannels() * 2, audioFormat.getSampleRate(),
						false)
				AudioInputStream newStream = AudioSystem.getAudioInputStream(
						newFormat, m_audioInputStream)
				audioFormat = newFormat
				m_audioInputStream = newStream
			}

			DataLine.Info info = new DataLine.Info(SourceDataLine.class,audioFormat)
			m_line = (SourceDataLine) AudioSystem.getLine(info)
			m_line.open(audioFormat, m_line.getBufferSize())
			m_line.start()

			int bufferSize = (int) audioFormat.getSampleRate() * audioFormat.getFrameSize()
			byte[] buffer = new byte[bufferSize]

			List<byte[]> loopBuffer = []
			List<Integer> loopBytesRead = []

			int bytesRead = 0
			while (bytesRead >= 0) {
				if(play_stop)
					break
				bytesRead = m_audioInputStream.read(buffer, 0, buffer.length)
				if (bytesRead >= 0) {
					m_line.write(buffer, 0, bytesRead)
				}
				if(loop){
					loopBuffer << buffer
					loopBytesRead << bytesRead
					buffer = new byte[bufferSize]
				}
			}
			if(loop)
				while(true){
					if(play_stop)
						break
					for(int i = 0; i < loopBuffer.size(); i++){
						if(play_stop)
							break
						buffer = loopBuffer[i]
						bytesRead = loopBytesRead[i]
						if (bytesRead >= 0)
							m_line.write(buffer, 0, bytesRead)
					}
				}
			m_line.drain()
			m_line.close()
		} catch (Exception e) {
			throw e
		}
	}

	public void stop(){
		play_stop = true
	}
}
